package com.ztc.ZtcOrder.service;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aqgj.shiro.ShiroDbRealm;
import com.aqgj.shiro.ShiroUser;
import com.aqgj.util.JsonWrapper;
import com.aqgj.util.Pager;
import com.ztc.ZtcCapitalIncome.bean.ZtcCapitalIncome;
import com.ztc.ZtcCapitalIncome.dao.ZtcCapitalIncomeDao;
import com.ztc.ZtcClassesSiteForSale.bean.ZtcClassesSiteForSale;
import com.ztc.ZtcClassesSiteForSale.dao.ZtcClassesSiteForSaleDao;
import com.ztc.ZtcRefundRatio.bean.ZtcRefundRatio;
import com.ztc.ZtcRefundRatio.dao.ZtcRefundRatioDao;
import com.ztc.ZtcRefundRecord.bean.ZtcRefundRecord;
import com.ztc.ZtcRefundRecord.dao.ZtcRefundRecordDao;
import com.ztc.ZtcTransport.bean.ZtcTransport;
import com.ztc.ZtcTransport.dao.ZtcTransportDao;
import com.ztc.ZtcTransportCapitalLog.bean.ZtcTransportCapitalLog;
import com.ztc.ZtcTransportCapitalLog.dao.ZtcTransportCapitalLogDao;
import com.ztc.ZtcTransportPercentageScale.bean.ZtcTransportPercentageScale;
import com.ztc.ZtcTransportPercentageScale.dao.ZtcTransportPercentageScaleDao;
import com.ztc.ZtcWallet.bean.ZtcWallet;
import com.ztc.ZtcWallet.dao.ZtcWalletDao;
import com.ztc.ZtcWallet.service.ZtcWalletManager;
import com.ztc.ZtcWalletLog.bean.ZtcWalletLog;
import com.ztc.ZtcWalletLog.dao.ZtcWalletLogDao;
import com.ztc.common.alipay.Alipay;
import com.ztc.common.util.OrderUtil;
import com.ztc.common.wechatpay.WeChatPay;
import com.ztc.common.wechatpay.model.RefundParameter;
import com.ztc.crawler.CripBusCrawler;
import com.ztc.crawler.DTO.CtripOrderDetailDTO;
import com.ztc.crawler.DTO.CtripOrderRefundTicketDTO;
import com.ztc.crawler.DTO.config.CripBusConfig;
import com.ztc.util.exceptions.BusinessException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ztc.ZtcClassesForSale.bean.ZtcClassesForSale;
import com.ztc.ZtcClassesForSale.dao.ZtcClassesForSaleDao;
import com.ztc.ZtcClassesForSale.service.ZtcClassesForSaleManager;
import com.ztc.ZtcClassesPriceForSale.bean.ZtcClassesPriceForSale;
import com.ztc.ZtcClassesPriceForSale.dao.ZtcClassesPriceForSaleDao;
import com.ztc.ZtcOrder.bean.ZtcOrder;
import com.ztc.ZtcOrder.dao.ZtcOrderDao;
import com.ztc.ZtcOrderTicket.bean.ZtcOrderTicket;
import com.ztc.ZtcOrderTicket.dao.ZtcOrderTicketDao;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service("ZtcOrder")
public class ZtcOrderManager {
    @Autowired
    ZtcOrderDao ztcOrderDao;
    @Autowired
    private ZtcClassesPriceForSaleDao ztcClassesPriceForSaleDao;
    @Autowired
    private ZtcClassesSiteForSaleDao ztcClassesSiteForSaleDao;
    @Autowired
    private ZtcClassesForSaleDao ztcClassesForSaleDao;
    @Autowired
    private ZtcClassesForSaleManager ztcClassesForSaleManager;
    @Autowired
    private ZtcOrderTicketDao ztcOrderTicketDao;
    @Autowired
    private ZtcTransportDao ztcTransportDao;
    @Autowired
    private ZtcRefundRatioDao ztcRefundRatioDao;
    @Autowired
    private ZtcRefundRecordDao ztcRefundRecordDao;
    @Autowired
    private ZtcWalletManager ztcWalletManager;
    @Autowired
    private ZtcTransportCapitalLogDao ztcTransportCapitalLogDao;
    @Autowired
    private ZtcCapitalIncomeDao ztcCapitalIncomeDao;
    @Autowired
    private ZtcWalletDao ztcWalletDao;
    @Autowired
    private ZtcWalletLogDao ztcWalletLogDao;
    @Autowired
    private ZtcTransportPercentageScaleDao ztcTransportPercentageScaleDao;

    private final Logger LOGGER = LogManager.getLogger(ShiroDbRealm.class);
    DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    private final BigDecimal percentage = new BigDecimal(100);

    public String getTicketInfo(String passengerInfos, ZtcClassesPriceForSale price,
                                List<ZtcOrderTicket> ztcOrderTickets) throws ParseException {
        String getResult = generateTicketInfos(passengerInfos, price, ztcOrderTickets);
        if ("01".equals(getResult) || "02".equals(getResult)) {
            return getResult;
        }
        return "1";
    }

    private String generateTicketInfos(String passengerInfos, ZtcClassesPriceForSale price,
                                       List<ZtcOrderTicket> ztcOrderTickets) throws ParseException {
        JSONArray passengerArray = JSON.parseArray(passengerInfos);
        String seatInfos = price.getSeatInfo();
        String[] seats = seatInfos.split("\\u0029,");
        for (int i = 0; i < seats.length; i++) {
            int seatIndex = seats[i].indexOf(")");
            if (seatIndex > 0) {
                seats[i] = seats[i].substring(1, seatIndex);
            } else {
                seats[i] = seats[i].substring(1);
            }
        }
        for (int i = 0; i < seats.length; i++) {
            for (int j = i + 1; j < seats.length; j++) {
                if (Float.valueOf(seats[i].split(",")[2]) > Float.valueOf(seats[j].split(",")[2])) {
                    String temp = seats[i];
                    seats[i] = seats[j];
                    seats[j] = temp;
                }
            }
        }
        for (int i = 0; i < seats.length; i++) {
            for (int j = i + 1; j < seats.length; j++) {
                if (seats[i].split(",")[2].equals(seats[j].split(",")[2])) {
                    if (Integer.valueOf(seats[i].split(",")[0]) > Integer.valueOf(seats[j].split(",")[0])) {
                        String temp = seats[i];
                        seats[i] = seats[j];
                        seats[j] = temp;
                    }
                }
            }
        }
        int remainChildSeatNumber = price.getRemainChildSeatNumber();
        int remainSeatNumber = price.getRemainSeatNumber();
        int adultPassengerNumber = 0;
        int childPassengerNumber = 0;
        // 鍒ゆ柇鏄惁鍙嚭绁�
        HashMap<String, Object> result = countPassengerInfo(seats, passengerArray, adultPassengerNumber,
                childPassengerNumber);
        adultPassengerNumber = Integer.parseInt(String.valueOf(result.get("adultPassengerNumber")));
        childPassengerNumber = Integer.parseInt(String.valueOf(result.get("childPassengerNumber")));
        // 璁剧疆鍓╀綑搴т綅涓庡墿浣欏効绔ヤ綅
        remainChildSeatNumber = remainChildSeatNumber - childPassengerNumber;
        remainSeatNumber = remainSeatNumber - adultPassengerNumber;
        if (remainChildSeatNumber < 0) {
            return "02";
        }
        if (remainSeatNumber < 0) {
            return "01";
        }
        for (int i = 0; i < passengerArray.size(); i++) {
            JSONObject passenger = passengerArray.getJSONObject(i);
            // 鎵惧嚭鏈敭搴т綅
            if ("0".equals(passenger.getString("passengerType"))) {
                for (int j = 0; j < seats.length; j++) {
                    String[] seatTags = seats[j].split(",");
                    if ("0".equals(seatTags[1])) {
                        if ("0".equals(seatTags[3])) {
                            seats[j] = "(" + seatTags[0] + ",1," + seatTags[2] + "," + seatTags[3] + ")";
                            getZtcOrderTicket(ztcOrderTickets, passenger, seats[j]);
                            break;
                        }
                        if ("1".equals(seatTags[3])) {
                            seats[j] = "(" + seatTags[0] + ",1," + seatTags[2] + "," + seatTags[3] + ")";
                            getZtcOrderTicket(ztcOrderTickets, passenger, seats[j]);
                            break;
                        }
                        if ("2".equals(seatTags[3])) {
                            seats[j] = "(" + seatTags[0] + ",1," + seatTags[2] + "," + seatTags[3] + ")";
                            getZtcOrderTicket(ztcOrderTickets, passenger, seats[j]);
                            break;
                        }
                    }
                    seats[j] = "(" + seatTags[0] + "," + seatTags[1] + "," + seatTags[2] + "," + seatTags[3] + ")";
                }
            } else if ("1".equals(passenger.getString("passengerType"))) {
                String seat = "(-1,1,0,3)";
                getZtcOrderTicket(ztcOrderTickets, passenger, seat);
            }
        }
        return "1";
    }

    private HashMap<String, Object> countPassengerInfo(String[] seats, JSONArray passengerArray,
                                                       int adultPassengerNumber, int childPassengerNumber) {
        HashMap<String, Object> result = new HashMap<String, Object>();
        for (int j = 0; j < passengerArray.size(); j++) {
            JSONObject passenger = passengerArray.getJSONObject(j);
            // 鎴愪汉
            if ("0".equals(passenger.getString("passengerType"))) {
                adultPassengerNumber++;
            }
            // 鍎跨
            if ("1".equals(passenger.getString("passengerType"))) {
                childPassengerNumber++;
            }
        }
        result.put("adultPassengerNumber", adultPassengerNumber);
        result.put("childPassengerNumber", childPassengerNumber);
        return result;
    }

    private void getZtcOrderTicket(List<ZtcOrderTicket> ztcOrderTickets, JSONObject passenger, String seat)
            throws ParseException {
        int seatIndex = seat.indexOf(")");
        if (seatIndex > 0) {
            seat = seat.substring(1, seatIndex);
        } else {
            seat = seat.substring(1);
        }
        String[] seatTags = seat.split(",");
        ZtcOrderTicket ztcOrderTicket = new ZtcOrderTicket();
        ztcOrderTicket.setPassengerName(passenger.getString("name"));
        if (!"".equals(passenger.getString("passengerBirthDay"))) {
            ztcOrderTicket.setPassengerBirthday(dateFormat.parse(passenger.getString("passengerBirthDay")));
        }
        ztcOrderTicket.setPassengerType(passenger.getInteger("passengerType"));
        ztcOrderTicket.setPassengerCardNumber(passenger.getString("passengerCardNumber"));
        ztcOrderTicket.setPassengerCardType(passenger.getInteger("passengerCardType"));
        if (passenger.getInteger("passengerType") == 0) {
            ztcOrderTicket.setPrice(new BigDecimal(seatTags[2]));
            ztcOrderTicket.setSeatType(Integer.parseInt(seatTags[3]));
        } else {
            ztcOrderTicket.setPrice(BigDecimal.ZERO);
            ztcOrderTicket.setSeatType(3);
        }
        ztcOrderTicket.setSeatNumber(Integer.parseInt(seatTags[0]));
        ztcOrderTickets.add(ztcOrderTicket);
    }

    public String save(ZtcOrder ztcOrder, String id, List<ZtcOrderTicket> ztcOrderTickets) throws ParseException {
        if (ztcOrder.getType() == 0) {
            ZtcClassesPriceForSale classesPriceForSale = new ZtcClassesPriceForSale();
            classesPriceForSale.setId(id);
            ZtcClassesPriceForSale price = ztcClassesPriceForSaleDao.searchInfoEquals(classesPriceForSale).get(0);
            if (price.getStatus() == 1) {
                return "02";
            }
            String setBalanceResult = setBalance(ztcOrder, price, ztcOrderTickets);
            if ("01".equals(setBalanceResult)) {
                return setBalanceResult;
            }
            String modifyResult = modifyInfulencedPrice(price, ztcOrderTickets);
            if ("0".equals(modifyResult) || "01".equals(modifyResult)) {
                return modifyResult;
            }
            ztcOrder.setOrderNumber(getOrderNumber());
            String result = ztcOrderDao.save(ztcOrder);
            if (result != null) {
                for (ZtcOrderTicket ztcOrderTicket : ztcOrderTickets) {
                    ztcOrderTicket.setFkOrderId(ztcOrder.getId());
                    ztcOrderTicket.setStatus(0);
                    String saveResult = ztcOrderTicketDao.save(ztcOrderTicket);
                    if ("0".equals(saveResult)) {
                        return "0";
                    }
                }
                return "1";
            }
            return "0";
        } else {
            ztcOrder.setOrderNumber(getOrderNumber());
            if (ztcOrderDao.save(ztcOrder) != null) {
                return "1";
            }
            return "0";
        }
    }

    private String setBalance(ZtcOrder ztcOrder, ZtcClassesPriceForSale price, List<ZtcOrderTicket> ztcOrderTickets) {
        BigDecimal balance = BigDecimal.ZERO;
        String[] priceSeats = price.getSeatInfo().split("\\u0029,");
        for (int i = 0; i < priceSeats.length; i++) {
            int priceSeatIndex = priceSeats[i].indexOf(")");
            if (priceSeatIndex > 0) {
                priceSeats[i] = priceSeats[i].substring(1, priceSeatIndex);
            } else {
                priceSeats[i] = priceSeats[i].substring(1);
            }
            String priceTags[] = priceSeats[i].split(",");
            for (int j = 0; j < ztcOrderTickets.size(); j++) {
                ZtcOrderTicket ztcOrderTicket = ztcOrderTickets.get(j);
                if (ztcOrderTicket.getSeatNumber() == Integer.parseInt(priceTags[0])) {
                    if (!"0".equals(priceTags[1])) {
                        return "01";
                    } else {
                        if (ztcOrderTicket.getPassengerType() == 0) {
                            balance = balance.add(new BigDecimal(priceTags[2]));
                        } else {
                            balance = balance.add(BigDecimal.ZERO);
                        }
                    }
                }
            }
        }
        ztcOrder.setOrderBalance(balance);
        return "1";
    }

    private String modifyInfulencedPrice(ZtcClassesPriceForSale price, List<ZtcOrderTicket> ztcOrderTickets) {
        List<ZtcClassesPriceForSale> infulencedPriceList = ztcClassesPriceForSaleDao
                .getInfluencedClassesPriceForSale(price);
        String modifyResult = modifyInfulencedPriceAssitant(price, ztcOrderTickets, infulencedPriceList);
        if (modifyResult != null) {
            return modifyResult;
        }
        ZtcClassesForSale ztcClassesForSale = new ZtcClassesForSale();
        ztcClassesForSale.setId(price.getFkClassesForSaleId());
        ZtcClassesForSale classesForSale = ztcClassesForSaleDao.searchInfoEquals(ztcClassesForSale, null, null).get(0);
        ZtcClassesPriceForSale forSelectPrice = new ZtcClassesPriceForSale();
        forSelectPrice.setFkClassesForSaleId(price.getFkClassesForSaleId());
        List<ZtcClassesPriceForSale> priceList = ztcClassesPriceForSaleDao.searchInfoEquals(forSelectPrice);
        int count = 0;
        for (int i = 0; i < priceList.size(); i++) {
            ZtcClassesPriceForSale ztcClassesPriceForSale = priceList.get(i);
            if (ztcClassesPriceForSale.getStatus() == 1) {
                count++;
            }
        }
        if (count == priceList.size()) {
            classesForSale.setTicketStatus(1);
            String result = ztcClassesForSaleDao.update(classesForSale);
            if (!"1".equals(result)) {
                return "0";
            }
        }
        return "1";
    }

    private String modifyInfulencedPriceAssitant(ZtcClassesPriceForSale price, List<ZtcOrderTicket> ztcOrderTickets,
                                                 List<ZtcClassesPriceForSale> infulencedPriceList) {
        for (int i = 0; i < infulencedPriceList.size(); i++) {
            ZtcClassesPriceForSale ztcClassesPriceForSale = infulencedPriceList.get(i);
            int adultPassengerNumber = 0;
            int childPassengerNumber = 0;
            int seatNumber = ztcClassesPriceForSale.getRemainSeatNumber();
            int childSeatNumber = ztcClassesPriceForSale.getRemainChildSeatNumber();
            String[] priceSeats = ztcClassesPriceForSale.getSeatInfo().split("\\u0029,");
            for (int k = 0; k < ztcOrderTickets.size(); k++) {
                ZtcOrderTicket ztcOrderTicket = ztcOrderTickets.get(k);
                if (ztcOrderTicket.getSeatNumber() == -1) {
                    childPassengerNumber++;
                }
            }
            for (int j = 0; j < priceSeats.length; j++) {
                int priceSeatIndex = priceSeats[j].indexOf(")");
                if (priceSeatIndex > 0) {
                    priceSeats[j] = priceSeats[j].substring(1, priceSeatIndex);
                } else {
                    priceSeats[j] = priceSeats[j].substring(1);
                }
                String priceTags[] = priceSeats[j].split(",");
                for (int k = 0; k < ztcOrderTickets.size(); k++) {
                    ZtcOrderTicket ztcOrderTicket = ztcOrderTickets.get(k);
                    if (ztcOrderTicket.getSeatNumber() == Integer.parseInt(priceTags[0])) {
                        if (price.getId().equals(ztcClassesPriceForSale.getId())) {
                            if ("0".equals(priceTags[1])) {
                                priceSeats[j] = priceTags[0] + ",1," + priceTags[2] + "," + priceTags[3];
                                adultPassengerNumber++;
                            } else {
                                return "01";
                            }
                        } else {
                            if ("0".equals(priceTags[1])) {
                                priceSeats[j] = priceTags[0] + ",1," + priceTags[2] + "," + priceTags[3];
                                adultPassengerNumber++;
                            } else {
                                priceSeats[j] = priceTags[0] + "," + priceTags[1] + "," + priceTags[2] + ","
                                        + priceTags[3];
                            }

                        }
                    }
                }
            }
            String priceSeatInfo = "";
            for (int j = 0; j < priceSeats.length; j++) {
                if (j != priceSeats.length - 1) {
                    priceSeatInfo += "(" + priceSeats[j] + "),";
                } else {
                    priceSeatInfo += "(" + priceSeats[j] + ")";
                }
            }
            ztcClassesPriceForSale.setSeatInfo(priceSeatInfo);
            childSeatNumber = childSeatNumber - childPassengerNumber;
            seatNumber = seatNumber - adultPassengerNumber;
            if (seatNumber == 0) {
                ztcClassesPriceForSale.setStatus(1);
            }
            if (2 * childSeatNumber > seatNumber) {
                int moveNumber = (2 * childSeatNumber - seatNumber) / 2 + 1;
                childSeatNumber = childSeatNumber - moveNumber;
                if (childSeatNumber < 0) {
                    childSeatNumber = 0;
                }
            }
            ztcClassesPriceForSale.setRemainChildSeatNumber(childSeatNumber);
            ztcClassesPriceForSale.setRemainSeatNumber(seatNumber);
            String result = ztcClassesPriceForSaleDao.update(ztcClassesPriceForSale);
            if (!"1".equals(result)) {
                return "0";
            }
        }
        return null;
    }

    private String getOrderNumber() {
        Date date = new Date();
        DateFormat df = new SimpleDateFormat("yyyyMMddHH");
        Random rad = new Random();
        String radString = rad.nextInt(10000) + "";
        return df.format(date) + radString;
    }

    public List<ZtcOrder> searchInfo(ZtcOrder ztcOrder) {
        return ztcOrderDao.searchInfo(ztcOrder);
    }

    public String delete(String id, String transportId, String walletId, String priceId) {
        return ztcOrderDao.delete(id, transportId, walletId, priceId);
    }

    public String cancel(String id, String refundReason) {
        ZtcOrder ztcOrder = new ZtcOrder();
        ztcOrder.setId(id);
        ZtcOrder order = ztcOrderDao.searchInfo(ztcOrder).get(0);
        if (order.getStatus() == 3) {
            return "03";
        }
        if (order.getStatus() == 2) {
            order.setStatus(4);
            order.setRefundReason(refundReason);
            order.setRefundTime(new Date());
            String result = ztcOrderDao.update(order);
            if ("1".equals(result)) {
                String updateResult = updateZtcClassesPrice(order);
                if ("1".equals(updateResult)) {
                    return "2";
                }
            }
            return "02";
        } else {
            order.setStatus(3);
            order.setFinishTime(new Date());
            String result = ztcOrderDao.update(order);
            if ("1".equals(result)) {
                String updateResult = updateZtcClassesPrice(order);
                if ("1".equals(updateResult)) {
                    return "1";
                }
            }
            return "01";
        }
    }

    private String updateZtcClassesPrice(ZtcOrder order) {
        ZtcOrderTicket orderTicket = new ZtcOrderTicket();
        orderTicket.setFkOrderId(order.getId());
        List<ZtcOrderTicket> tickets = ztcOrderTicketDao.searchInfoEquals(orderTicket);
        for (int i = 0; i < tickets.size(); i++) {
            ZtcOrderTicket ticket = tickets.get(i);
            ticket.setStatus(1);
            String result = ztcOrderTicketDao.update(ticket);
            if ("0".equals(result)) {
                return "0";
            }
        }
        ZtcClassesPriceForSale orderPrice = new ZtcClassesPriceForSale();
        orderPrice.setId(order.getFkZtcClassesPriceForSaleId());
        ZtcClassesPriceForSale price = ztcClassesPriceForSaleDao.searchInfoEquals(orderPrice).get(0);
        return updateInfulencedPrice(price, tickets);
    }

    private String updateInfulencedPrice(ZtcClassesPriceForSale price, List<ZtcOrderTicket> ztcOrderTickets) {
        List<ZtcClassesPriceForSale> infulencedPriceList = ztcClassesPriceForSaleDao
                .getInfluencedClassesPriceForSale(price);
        String modifyResult = updateInfulencedPriceAssist(price, ztcOrderTickets, infulencedPriceList);
        if (modifyResult != null) {
            return modifyResult;
        }
        ZtcClassesForSale ztcClassesForSale = new ZtcClassesForSale();
        ztcClassesForSale.setId(price.getFkClassesForSaleId());
        ZtcClassesForSale classesForSale = ztcClassesForSaleDao.searchInfoEquals(ztcClassesForSale, null, null).get(0);
        List<ZtcClassesPriceForSale> priceList = ztcClassesPriceForSaleDao.searchInfoEquals(price);
        boolean haveOnSale = false;
        for (int i = 0; i < priceList.size(); i++) {
            ZtcClassesPriceForSale ztcClassesPriceForSale = priceList.get(i);
            if (ztcClassesPriceForSale.getStatus() == 0) {
                haveOnSale = true;
            }
        }
        if (haveOnSale) {
            classesForSale.setTicketStatus(0);
            String result = ztcClassesForSaleDao.update(classesForSale);
            if (!"1".equals(result)) {
                return "0";
            }
        }
        return "1";
    }

    private String updateInfulencedPriceAssist(ZtcClassesPriceForSale price, List<ZtcOrderTicket> ztcOrderTickets,
                                        List<ZtcClassesPriceForSale> infulencedPriceList) {
        for (int i = 0; i < infulencedPriceList.size(); i++) {
            ZtcClassesPriceForSale ztcClassesPriceForSale = infulencedPriceList.get(i);
            boolean isStopSell = false;
            ZtcClassesForSale ztcClassesForSale = new ZtcClassesForSale();
            ztcClassesForSale.setId(ztcClassesPriceForSale.getFkClassesForSaleId());
            ZtcClassesForSale ztcClassesForSaleBean = ztcClassesForSaleManager.searchInfoEquals(ztcClassesForSale)
                    .get(0);
            if (ztcClassesForSaleBean.getTicketStatus() == 1) {
                isStopSell = true;
            }
            int adultPassengerNumber = 0;
            int childPassengerNumber = 0;
            if(ztcClassesPriceForSale.getType()==0){
                String[] priceSeats = ztcClassesPriceForSale.getSeatInfo().split("\\u0029,");
                HashMap<String, Object> resultMap = generateSeatInfoAssistant(priceSeats, ztcOrderTickets, isStopSell,
                        price, ztcClassesPriceForSale, adultPassengerNumber, childPassengerNumber);
                adultPassengerNumber = Integer.parseInt(String.valueOf(resultMap.get("adultPassengerNumber")));
                childPassengerNumber = Integer.parseInt(String.valueOf(resultMap.get("childPassengerNumber")));
                String priceSeatInfo = "";
                for (int j = 0; j < priceSeats.length; j++) {
                    if ("".equals(priceSeats[j])) {
                        continue;
                    }
                    if (j != priceSeats.length - 1) {
                        priceSeatInfo += "(" + priceSeats[j] + "),";
                    } else {
                        priceSeatInfo += "(" + priceSeats[j] + ")";
                    }
                }
                ztcClassesPriceForSale.setSeatInfo(priceSeatInfo);
                int seatNumber = ztcClassesPriceForSale.getRemainSeatNumber() + adultPassengerNumber;
                int childSeatNumber = ztcClassesPriceForSale.getRemainChildSeatNumber() + childPassengerNumber;
                ztcClassesPriceForSale.setRemainSeatNumber(seatNumber);
                if (ztcClassesPriceForSale.getStatus() == 1) {
                    if (!isStopSell) {
                        ztcClassesPriceForSale.setStatus(0);
                    }
                }
                int calculateChildSeatNumber = (int) (seatNumber / 10);
                if (calculateChildSeatNumber < childSeatNumber) {
                    ztcClassesPriceForSale.setRemainChildSeatNumber(calculateChildSeatNumber);
                } else {
                    ztcClassesPriceForSale.setRemainChildSeatNumber(childSeatNumber);
                }

            } else if(ztcClassesPriceForSale.getType()==1){
                for (int k = 0; k < ztcOrderTickets.size(); k++) {
                    ZtcOrderTicket ztcOrderTicket = ztcOrderTickets.get(k);
                    if (ztcOrderTicket.getPassengerType() == 1) {
                        childPassengerNumber++;
                    }else if(ztcOrderTicket.getPassengerType() == 0){
                        adultPassengerNumber++;
                    }
                }
                ztcClassesPriceForSale.setRemainSeatNumber(ztcClassesPriceForSale.getRemainSeatNumber()+adultPassengerNumber);
                ztcClassesPriceForSale.setRemainChildSeatNumber(ztcClassesPriceForSale.getRemainChildSeatNumber()+childPassengerNumber);
                if(ztcClassesPriceForSale.getStatus()==1){
                    ZtcClassesSiteForSale ztcClassesSiteForSale=ztcClassesSiteForSaleDao.get(ztcClassesPriceForSale.getFkEndClassesSiteForSaleId());
                    if(ztcClassesSiteForSale.getStatus() != null && ztcClassesSiteForSale.getStatus()==0){
                        ztcClassesPriceForSale.setStatus(0);
                    }
                }
            }
            String result = ztcClassesPriceForSaleDao.update(ztcClassesPriceForSale);
            if (!"1".equals(result)) {
                return "0";
            }
        }
        return null;
    }

    private HashMap<String, Object> generateSeatInfoAssistant(String[] priceSeats, List<ZtcOrderTicket> ztcOrderTickets,
                                                              boolean isStopSell, ZtcClassesPriceForSale price, ZtcClassesPriceForSale ztcClassesPriceForSale,
                                                              int adultPassengerNumber, int childPassengerNumber) {
        HashMap<String, Object> result = new HashMap<String, Object>();
        for (int k = 0; k < ztcOrderTickets.size(); k++) {
            ZtcOrderTicket ztcOrderTicket = ztcOrderTickets.get(k);
            if (ztcOrderTicket.getPassengerType() == 1) {
                childPassengerNumber++;
            }
        }
        for (int j = 0; j < priceSeats.length; j++) {
            int priceSeatIndex = priceSeats[j].indexOf(")");
            if (priceSeatIndex > 0) {
                priceSeats[j] = priceSeats[j].substring(1, priceSeatIndex);
            } else {
                priceSeats[j] = priceSeats[j].substring(1);
            }
            String priceTags[] = priceSeats[j].split(",");
            for (int k = 0; k < ztcOrderTickets.size(); k++) {
                ZtcOrderTicket ztcOrderTicket = ztcOrderTickets.get(k);
                if (ztcOrderTicket.getPassengerType() == 0) {
                    if (ztcOrderTicket.getSeatNumber() == Integer.parseInt(priceTags[0])) {
                        if (isStopSell) {
                            priceSeats[j] = "";
                        } else {
                            if (price.getId().equals(ztcClassesPriceForSale.getId())) {
                                priceSeats[j] = priceTags[0] + ",0," + priceTags[2] + "," + priceTags[3];
                                adultPassengerNumber++;
                            } else {
                                if ("1".equals(priceTags[1])) {
                                    priceSeats[j] = priceTags[0] + ",0," + priceTags[2] + "," + priceTags[3];
                                    adultPassengerNumber++;
                                } else {
                                    adultPassengerNumber++;
                                }
                            }
                        }
                    }
                }
            }
        }
        result.put("adultPassengerNumber", adultPassengerNumber);
        result.put("childPassengerNumber", childPassengerNumber);
        return result;
    }

    public String update(ZtcOrder ztcOrder) throws ParseException {
        return ztcOrderDao.update(ztcOrder);
    }

    public ZtcOrder get(String id) {
        return ztcOrderDao.get(id);
    }

    /**
     * 获取订单信息
     */
    public Map getZcOrderByOrderNumber(String orderNumber) {
        Map orderMap = ztcOrderDao.getZcOrderByOrderNumber(orderNumber);
        ZtcOrder order = ztcOrderDao.findUniqueBy("orderNumber", orderNumber);
        if (order != null && order.getOrderType() != 1 && order.getOrderType() != 3) {
            throw new BusinessException("非平台订单不支持退款");
        }
        return orderMap;
    }

    /**
     * 获取当前公司下的所有订单 （直通车）
     */
    public Pager<Map> getAllZcOrderByCompanyId(ZtcTransport ztcTransport, Integer pageSize, Integer pageNumber,
                                               String orderId, String startDate, String endDate,String departDateStart,String departDateEnd,String contactName,String contactPhone,String orderStatus) {
        return ztcOrderDao.getAllZcOrderByCompanyId(ztcTransport, pageSize, pageNumber, orderId, startDate,endDate,departDateStart,departDateEnd,contactName,contactPhone,orderStatus);
    }

    /**
     * 导出所有订单 （直通车）
     */
    public List<Map> getAllZcOrderByCompanyId(ZtcTransport ztcTransport,String orderId, String startDate, String endDate,String departDateStart,String departDateEnd,String contactName,String contactPhone,String orderStatus) {
        return ztcOrderDao.getAllZcOrderByCompanyId(ztcTransport, orderId, startDate,endDate,departDateStart,departDateEnd,contactName,contactPhone,orderStatus);
    }

    /**
     * 获取当前公司下的所有订单 （充值）
     */
    public Pager<Map> getRechargeList(Integer pageSize, Integer pageNumber, String orderId, Integer payType,
                                      String startDate, String endDate) {
        return ztcOrderDao.getRechargeList(pageSize, pageNumber, orderId, payType, startDate, endDate);
    }

    /**
     * 获取当前公司下的所有订单 （去哪儿）
     */
    public Pager<Map> getCtripList(Integer pageSize, Integer pageNumber, String orderId, Integer payType,
                                   String startDate, String endDate) {
        return ztcOrderDao.getCtripList(pageSize, pageNumber, orderId, payType, startDate, endDate);
    }

    /**
     * 获取订单详情
     */
    public HashMap<String, Object> getOrderDetail(String orderId, Integer orderType, Integer type) {
        List<Object[]> result = ztcOrderDao.getOrderDetail(orderId, orderType, type);
        HashMap<String, Object> map = new HashMap<>();
        if (result.size() == 0) {
            return JsonWrapper.failureWrapperMsg("获取订单信息失败！");
        }
        Object[] objects = result.get(0);
        if (objects[0] == null) {
            return JsonWrapper.failureWrapperMsg("获取订单信息失败！");
        }
        switch (orderType) {
            case 0:
                map.put("fullName", objects[0]); // 发布公司名
                map.put("routeName", objects[1]); // 线路名
                map.put("orderNumber", objects[2]); // 订单编号
                map.put("orderStatus", objects[3]); // 订单状态
                map.put("price", objects[4]); // 订单价格
                map.put("payPrice", objects[5]); // 实际支付
                map.put("refundPrice", objects[6]); // 退款金额（退款）
                map.put("contactName", objects[7]); // 联系人
                map.put("contactTel", objects[8]); // 联系人手机
                map.put("orderType", objects[9]); // 类型：0.车票，1.充值
                map.put("payType", objects[10]); // 支付类型：1.余额2.支付宝3.微信
                map.put("orderTime", objects[11]); // 下单时间
                map.put("payTime", objects[12]); // 支付时间
                map.put("fullTime", objects[13]); // 完成时间
                map.put("refundTime", objects[14]); // 退款时间（退款）
                map.put("refundRemark", objects[15]);// 退款说明
                String[] passengers = objects[16].toString().split(";"); // 乘客
                List<HashMap<String, Object>> resultPerson = new ArrayList<>();
                if (passengers.length > 0) {
                    HashMap<String, Object> map1 = null;
                    for (String temp : passengers) {
                        map1 = new HashMap<>();
                        String[] tempPerson = temp.split(",");
                        map1.put("passengerName", tempPerson[0]); // 乘客姓名
                        map1.put("passengerBirthday", tempPerson[1]); // 乘客生日
                        map1.put("passengerType", tempPerson[2]); // 乘客类型
                        map1.put("passengerCardNumber", tempPerson[3]);// 乘客证件号码
                        map1.put("passengerCardType", tempPerson[4]); // 乘客证件类型
                        map1.put("seatNumber", tempPerson[5]); // 乘客座位号
                        map1.put("seatType", tempPerson[6]); // 乘客座位类型
                        map1.put("price", tempPerson[7]); // 乘客支付价格
                        resultPerson.add(map1);
                    }
                }
                map.put("person", resultPerson);
                map.put("id", objects[17]);
                //平台订单，顺风车订单
                if(type==3||type==1){
                    map.put("type", objects[18]);
                }
                break;
            case 1:
                map.put("orderNumber", objects[0]);
                map.put("orderStatus", objects[1]);
                map.put("price", objects[2]);
                map.put("payPrice", objects[3]);
                map.put("contactName", objects[4]);
                map.put("contactTel", objects[5]);
                map.put("orderType", objects[6]);
                map.put("payType", objects[7]);
                map.put("orderTime", objects[8]);
                map.put("payTime", objects[9]);
                map.put("fullTime", objects[10]);
                map.put("userAccount", objects[11]);
                map.put("userRealName", objects[12]);
                map.put("userTel", objects[13]);
                map.put("userStatus", objects[14]);
                break;
            default:
                return JsonWrapper.successWrapper(map);
        }
        return JsonWrapper.successWrapper(map);
    }

    public List<ZtcOrder> getAll() {
        return ztcOrderDao.getAll();
    }

    /**
     * 该订单是否能退款
     *
     * @param orderInfoVo
     * @return
     */
    public boolean isRefund(Map orderInfoVo, String fromTransportId) {
        long nowTime = System.currentTimeMillis();
        long departure = 0;
        if(orderInfoVo.get("order_type").toString() != null && "3".equals(orderInfoVo.get("order_type").toString())){
            try {
                departure = sdf.parse(orderInfoVo.get("departure_time").toString()).getTime();
            } catch (ParseException e) {
                e.printStackTrace();
            }
            // 计算小时差
            float hours = (departure - nowTime) / (float) (1000 * 60 * 60);
            if (hours > 2) {
                return true;
            }else{
                return false;
            }
        }
        ZtcTransport transport = ztcTransportDao.get(fromTransportId);
        String transportId = transport.getId();
        if (transport.getType() == 4) {
            transportId = transport.getParentId();
        }
        ZtcRefundRatio refundRatio = ztcRefundRatioDao.getRefundRatioRefundTimeByTransportId(transportId);
        long departureTime = 0;
        try {
            departureTime = sdf.parse(orderInfoVo.get("departure_time").toString()).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (refundRatio != null) {
            nowTime += refundRatio.getEndTime() * (1000 * 60 * 60);
            // 计算小时差
            float hours = (departureTime - nowTime) / (float) (1000 * 60 * 60);
            if (hours > 0) {
                return true;
            }
        } else {
            if (departureTime > nowTime) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取退款金额
     *
     * @param orderInfoVo 订单信息
     * @param order       订单信息
     * @return
     */
    private Map<String, BigDecimal> getRefundFee(Map orderInfoVo, ZtcOrder order) {
        Map<String, BigDecimal> refundMap = new HashMap<>();
        ZtcTransport transport = ztcTransportDao.get(order.getFkTransportId());
        String transportId = transport.getId();
        if (transport.getType() == 4) {
            transportId = transport.getParentId();
        }
        List<ZtcRefundRatio> refundRatioList = ztcRefundRatioDao.getRefundRatioTransportId(transportId);
        long departureTime = 0;
        try {
            departureTime = sdf.parse(orderInfoVo.get("departure_time").toString()).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        long nowTime = System.currentTimeMillis();
        // 计算小时差
        int hours = (int) ((departureTime - nowTime) / (1000 * 60 * 60));
        BigDecimal chargeScale = BigDecimal.ZERO;
        for (ZtcRefundRatio refundRatio : refundRatioList) {
            if (hours >= refundRatio.getStartTime() && hours <= refundRatio.getEndTime()) {
                chargeScale = refundRatio.getChargeScale();
            }
        }
        BigDecimal refundScale = percentage.subtract(chargeScale);
        BigDecimal refundFee = order.getOrderBalance().multiply(refundScale).divide(percentage, 2,
                BigDecimal.ROUND_DOWN);
        BigDecimal payFee = order.getPayBalance();
        if (refundFee.compareTo(payFee) == 1) {
            refundFee = payFee;
        }
        BigDecimal penaltyFee = BigDecimal.ZERO;
        if (refundFee.compareTo(payFee) == -1) {
            penaltyFee = payFee.subtract(refundFee);
        }
        refundMap.put("refundFee", refundFee);
        refundMap.put("penaltyFee", penaltyFee);
        return refundMap;
    }

    @Transactional(rollbackFor = RuntimeException.class, propagation = Propagation.REQUIRES_NEW)
    public void cancelOrder(String orderNumber, int refundType, BigDecimal refundMoney) {
        ZtcOrder ztcOrder = ztcOrderDao.findUniqueBy("orderNumber", orderNumber);
        if (ztcOrder == null) {
            throw new BusinessException("订单不存在");
        }
        if (ztcOrder.getStatus() < 1) {
            throw new BusinessException("该订单状态不能退款");
        }
        if (ztcOrder.getOrderType() != 1 && ztcOrder.getOrderType() != 3) {
            throw new BusinessException("非平台订单不支持退款");
        }
        //订单完成，退款判断时间差
        if(ztcOrder.getStatus()==3) {
            //时间差
            Long differtime = System.currentTimeMillis()-ztcOrder.getFinishTime().getTime();
            if(differtime/1000>=604800){
                throw new BusinessException("订单完成超过7天时间，无法退款");
            }
        }
        //订单退款，退款判断时间差
        if(ztcOrder.getStatus()==5) {
            //时间差
            Long differtime = System.currentTimeMillis()-ztcOrder.getRefundTime().getTime();
            if(differtime/1000>=604800){
                throw new BusinessException("退款订单超过7天时间，无法退款");
            }
        }
        if (refundMoney != null && refundType != 3) {
            throw new BusinessException("参数错误");
        }
        switch (refundType) {
            // 退违约金
            case 1:
                if (ztcOrder.getRefundStatus() == null) {
                    throw new BusinessException("退款失败，该订单无违约金可退");
                }
                if (ztcOrder.getRefundStatus() == 1) {
                    throw new BusinessException("退款失败，该订单已退全款");
                }
                BigDecimal refundFee = ztcOrder.getPayBalance().subtract(ztcOrder.getRefundBalance());
                refundBegin(ztcOrder, refundFee, BigDecimal.ZERO, true, "后台退违约金");
                break;
            case 2:
                checkedRefund(ztcOrder.getRefundStatus());
                refundFee = ztcOrder.getPayBalance();
                BigDecimal penaltyFee = BigDecimal.ZERO;
                if (ztcOrder.getStatus() == 3) {
                    if(ztcOrder.getOrderType() != 3){
                        // 退款公司处理
                        refundCompanyAccount(ztcOrder.getId(), ztcOrder.getOrderNumber());
                    }else {
                        ZtcWalletLog walletLog = ztcWalletLogDao.findBy("fkOrderId", ztcOrder.getId(), "type", 14).get(0);
                        ZtcWallet wallet = ztcWalletManager.getWalletByUserId(walletLog.getFkUserId());
                        wallet.setMoney(wallet.getMoney().subtract(walletLog.getMoney()));
                        ztcWalletDao.update(wallet);
                        ztcWalletManager.saveWalletLog(wallet.getFkUserId(), ztcOrder.getId(), walletLog.getMoney().negate(), wallet.getMoney(), 15);
                        List<ZtcCapitalIncome> capitalIncomeList = ztcCapitalIncomeDao.findBy("orderId", orderNumber);
                        if (capitalIncomeList != null && capitalIncomeList.size() > 0) {
                            ZtcCapitalIncome capitalIncome = capitalIncomeList.get(0);
                            saveCapitalIncome(capitalIncome.getOrderId(), capitalIncome.getMoney(), capitalIncome.getIncomeMoney().negate(),
                                    2, "退票出账");
                        }
                    }
                }
                refundBegin(ztcOrder, refundFee, penaltyFee, false, "后台全款退");
                break;
            case 3:
                checkedRefund(ztcOrder.getRefundStatus());
                if (ztcOrder.getOrderBalance().compareTo(refundMoney) < 0) {
                    throw new BusinessException("退款金额不能大于订单金额");
                }
                // 违约金
                penaltyFee = ztcOrder.getOrderBalance().subtract(refundMoney);
                // 退款公司处理
                if (ztcOrder.getStatus() == 3) {
                    if(ztcOrder.getOrderType() != 3){
                        // 退款公司处理
                        refundCompanyAccount(ztcOrder.getId(), ztcOrder.getOrderNumber());
                    }else {
                        ZtcWalletLog walletLog = ztcWalletLogDao.findBy("fkOrderId", ztcOrder.getId(), "type", 14).get(0);
                        ZtcWallet wallet = ztcWalletManager.getWalletByUserId(walletLog.getFkUserId());
                        wallet.setMoney(wallet.getMoney().subtract(walletLog.getMoney()));
                        ztcWalletDao.update(wallet);
                        ztcWalletManager.saveWalletLog(wallet.getFkUserId(), ztcOrder.getId(), walletLog.getMoney().negate(), wallet.getMoney(), 15);
                        List<ZtcCapitalIncome> capitalIncomeList = ztcCapitalIncomeDao.findBy("orderId", orderNumber);
                        if (capitalIncomeList != null && capitalIncomeList.size() > 0) {
                            ZtcCapitalIncome capitalIncome = capitalIncomeList.get(0);
                            saveCapitalIncome(capitalIncome.getOrderId(), capitalIncome.getMoney(), capitalIncome.getIncomeMoney().negate(),
                                    2, "退票出账");
                        }
                    }
                }
                refundBegin(ztcOrder, refundMoney, penaltyFee, false, "后台自定义退款");
                break;
            default:
                throw new BusinessException("退款类型参数错误");
        }
    }

    private void checkedRefund(Integer refundStatus) {
        if (refundStatus != null) {
            if (refundStatus == 1) {
                throw new BusinessException("退款失败，该订单已退全款");
            }
            if (refundStatus == 2) {
                throw new BusinessException("退款失败，该订单只能申请退违约金");
            }
        }
    }

    /**
     * 申请退款（后台退票）
     *
     * @param id           订单ID
     * @param refundReason 退票原因
     */
    @Transactional(rollbackFor = RuntimeException.class, propagation = Propagation.REQUIRES_NEW)
    public void cancelOrder(String id, String refundReason) {
        Map order = ztcOrderDao.getCtripPayDetailById(id);
        ZtcOrder ztcOrder = ztcOrderDao.get(id);
        if ((Integer.parseInt(order.get("status").toString())) != 1
                && (Integer.parseInt(order.get("status").toString())) != 2) {
            throw new BusinessException("该订单状态不能退款");
        }
        // 如果是携程订单退款
        if (Integer.parseInt(order.get("order_type").toString()) == 2) {
            try {
                if (System.currentTimeMillis() >= sdf.parse(order.get("departure_date").toString()).getTime()) {
                    throw new BusinessException("该订单不在规定退款时间内");
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
            CtripOrderDetailDTO ctripOrderDetailDTO = new CtripOrderDetailDTO();
            ctripOrderDetailDTO.setOrderNumber(order.get("ctrip_order_number").toString());
            JSONObject detailObject = CripBusCrawler.start(ctripOrderDetailDTO, CripBusConfig.cripBusOrderDetail);
            if (!"1".equals(detailObject.getString("code"))) {
                throw new BusinessException("退款失败，请联系客服");
            }
            JSONArray ticketInfoArray = detailObject.getJSONObject("return").getJSONArray("ticketInfo");
            Set<String> setTicketIdSet = new HashSet<>(2);
            for (Iterator iterator = ticketInfoArray.iterator(); iterator.hasNext(); ) {
                JSONObject object = (JSONObject) iterator.next();
                setTicketIdSet.add(object.getString("ticketId"));
            }
            if (setTicketIdSet.size() <= 0) {
                throw new BusinessException("退款失败，请联系客服");
            }
            CtripOrderRefundTicketDTO ctripOrderRefundTicketDTO = new CtripOrderRefundTicketDTO();
            ctripOrderRefundTicketDTO.setOrderNumber(order.get("ctrip_order_number").toString());
            ctripOrderRefundTicketDTO.setTicketId(setTicketIdSet);
            JSONObject jsonObject = CripBusCrawler.start(ctripOrderRefundTicketDTO,
                    CripBusConfig.cripBusOrderRefundTicket);
            if (!"1".equals(jsonObject.getString("code"))) {
                throw new BusinessException("退款失败，请联系客服");
            }
            ztcOrder.setStatus(4);
            ztcOrder.setRefundReason(refundReason);
            ztcOrderDao.update(ztcOrder);
            return;
        }
        Map orderInfoVo;
        if(ztcOrder.getOrderType() != 3){
            orderInfoVo = ztcOrderDao.getOrderById(id);
        }else{
            orderInfoVo = ztcOrderDao.getPrivateOrderById(id);
        }
        if (!isRefund(orderInfoVo, order.get("fk_transport_id").toString())) {
            throw new BusinessException("该订单不在规定退款时间内");
        }
        // 退款金额
        BigDecimal refundFee;
        // 违约金
        BigDecimal penaltyFee;
        if("3".equals(orderInfoVo.get("order_type").toString())){
            refundFee = ztcOrder.getOrderBalance().multiply(new BigDecimal(0.9));
            penaltyFee = ztcOrder.getOrderBalance().multiply(new BigDecimal(0.1));
        }else{
            Map<String, BigDecimal> refundFeeMap = getRefundFee(orderInfoVo, ztcOrder);
            refundFee = refundFeeMap.get("refundFee");
            penaltyFee = refundFeeMap.get("penaltyFee");
        }
        refundBegin(ztcOrder, refundFee, penaltyFee, false, refundReason);
        // 退款公司处理
        // refundCompanyAccount(ztcOrder.getId(),ztcOrder.getOrderNumber(),penaltyFee);
    }


    /**
     * 退款操作
     *
     * @param order              订单信息
     * @param refundFee          退款金额
     * @param penaltyFee         违约金
     * @param isRefundPenaltyFee 是否为退违约金
     * @param refundReason       退票原因
     */
    private void refundBegin(ZtcOrder order, BigDecimal refundFee, BigDecimal penaltyFee, boolean isRefundPenaltyFee,
                             String refundReason) {
        // 退款记录
        ZtcRefundRecord refundRecord = new ZtcRefundRecord();
        switch (order.getPayType()) {
            // 余额退款
            case 1:
                ztcWalletManager.saveThreeRebateLogAndUpdateWalletByRefund(order, true, refundFee, isRefundPenaltyFee);
                break;
            // 支付宝退款
            case 2:
                String refundNo = OrderUtil.getOrderNumber("ATK");
                boolean isOk = Alipay.refundAliPay(order.getOrderNumber(), refundFee.toString(), refundNo, "取消订单退款");
                if (!isOk) {
                    throw new BusinessException("退款失败，请联系客服");
                }
                refundRecord.setAliRefundNumber(refundNo);
                ztcWalletManager.saveThreeRebateLogAndUpdateWalletByRefund(order, false, refundFee, isRefundPenaltyFee);
                break;
            // 微信退款
            case 3:
                RefundParameter refundParameter = new RefundParameter();
                refundParameter.setOutTradeNo(order.getOrderNumber());
                refundNo = OrderUtil.getOrderNumber("WTK");
                refundParameter.setOutRefundNo(refundNo);
                refundParameter.setRefundDesc("取消订单退款");
                refundParameter.setTotalFee(order.getOrderBalance().multiply(percentage).intValue());
                refundParameter.setRefundFee(refundFee.multiply(percentage).intValue());
                boolean isTrue;
                try {
                    isTrue = WeChatPay.refundApply(refundParameter, order.getPayMode());
                } catch (Exception e) {
                    LOGGER.error(e.getMessage(), e);
                    throw new BusinessException("退款失败，请联系客服");
                }
                if (!isTrue) {
                    throw new BusinessException("退款失败，请联系客服");
                }
                refundRecord.setWxRefundNumber(refundNo);
                ztcWalletManager.saveThreeRebateLogAndUpdateWalletByRefund(order, false, refundFee, isRefundPenaltyFee);
                break;
            default:
                break;
        }
        refundRecord.setType("1");
        order.setRefundStatus(1);
        if (penaltyFee.compareTo(BigDecimal.ZERO) == 1 && !isRefundPenaltyFee) {
            refundRecord.setType("2");
            order.setRefundStatus(2);
            // 处理违约金处理
            if(order.getOrderType() != 3){
                Map orderMap = ztcOrderDao.getPenaltyOrderById(order.getId());
                handlePenaltyFee(orderMap, penaltyFee);
            }else{
                saveCapitalIncome(order.getOrderNumber(),order.getOrderBalance(),penaltyFee,3,"违约金进账");
            }
            // saveCapitalIncome(order.getOrderNumber(),order.getOrderBalance(),penaltyFee,3,"违约金进账");
        }
        order.setRefundBalance(refundFee);
        if (isRefundPenaltyFee) {
            refundRecord.setType("3");
            order.setRefundBalance(order.getPayBalance());
            // ZtcCapitalIncome capitalIncome =
            // ztcCapitalIncomeDao.findUniqueBy("orderId",order.getOrderNumber());
            // 退违约金处理
            if(order.getOrderType() != 3) {
                handlePenaltyRefund(order.getId(), order.getOrderNumber());
            }else{
                ZtcCapitalIncome capitalIncome = ztcCapitalIncomeDao.findUniqueBy("orderId",order.getOrderNumber());
                saveCapitalIncome(capitalIncome.getOrderId(),capitalIncome.getMoney(),capitalIncome.getIncomeMoney().negate(),4,"违约金出账");
            }
            // saveCapitalIncome(capitalIncome.getOrderId(),capitalIncome.getMoney(),capitalIncome.getIncomeMoney().negate(),4,"违约金出账");
        }
        ShiroUser shiroUser = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
        refundRecord.setFkManagerId(shiroUser.getId());
        refundRecord.setFkOrderId(order.getId());
        refundRecord.setMoney(refundFee);
        refundRecord.setAddTime(new Date());
        ztcRefundRecordDao.save(refundRecord);
        order.setStatus(5);
        order.setRefundReason(refundReason);
        order.setRefundTime(new Date());
        ztcOrderDao.update(order);
        if ((order.getOrderType() == 1 || order.getOrderType() == 3) && !isRefundPenaltyFee) {
            updateZtcClassesPrice(order);
        }
    }

    /**
     * 退款公司处理
     *
     * @param businessId  业务ID
     * @param orderNumber 业务ID
     */
    private void refundCompanyAccount(String businessId, String orderNumber) {
        List<ZtcTransportCapitalLog> transportCapitalLogList = ztcTransportCapitalLogDao
                .getTransportCapitalLogAndTransportById(businessId, false);
        if (transportCapitalLogList == null || transportCapitalLogList.size() == 0) {
            return;
        }
        ZtcWallet wallet;
        for (ZtcTransportCapitalLog transportCapitalLog : transportCapitalLogList) {
            String transportId = transportCapitalLog.getZtcTransport().getId();
            Integer type = transportCapitalLog.getZtcTransport().getType();
            wallet = ztcWalletManager.getWalletByUserId(transportId);
            switch (type) {
                // 省管理公司
                case 1:
                    wallet.setMoney(wallet.getMoney().subtract(transportCapitalLog.getMoney()));
                    ztcWalletDao.update(wallet);
                    saveTransportCapitalLog(transportCapitalLog.getBusinessId(), transportId,
                            transportCapitalLog.getMoney().negate(), wallet.getMoney(), "10", "省级公司退票出账");
                    break;
                // 2地级市公司
                case 2:
                    wallet.setMoney(wallet.getMoney().subtract(transportCapitalLog.getMoney()));
                    ztcWalletDao.update(wallet);
                    saveTransportCapitalLog(transportCapitalLog.getBusinessId(), transportId,
                            transportCapitalLog.getMoney().negate(), wallet.getMoney(), "9", "地级公司退票出账");
                    break;
                // 运营公司
                case 3:
                    wallet.setMoney(wallet.getMoney().subtract(transportCapitalLog.getMoney()));
                    ztcWalletDao.update(wallet);
                    saveTransportCapitalLog(transportCapitalLog.getBusinessId(), transportId,
                            transportCapitalLog.getMoney().negate(), wallet.getMoney(), "8", "运营公司退票出账");
                    break;
                // 车方公司
                case 4:
                    wallet.setMoney(wallet.getMoney().subtract(transportCapitalLog.getMoney()));
                    ztcWalletDao.update(wallet);
                    saveTransportCapitalLog(transportCapitalLog.getBusinessId(), transportId,
                            transportCapitalLog.getMoney().negate(), wallet.getMoney(), "7", "车方公司退票出账");
                    break;
                default:
                    break;
            }
        }
        List<ZtcCapitalIncome> capitalIncomeList = ztcCapitalIncomeDao.findBy("orderId", orderNumber);
        if (capitalIncomeList == null || capitalIncomeList.size() == 0) {
            return;
        }
        ZtcCapitalIncome capitalIncome = capitalIncomeList.get(0);
        saveCapitalIncome(capitalIncome.getOrderId(), capitalIncome.getMoney(), capitalIncome.getIncomeMoney().negate(),
                2, "退票出账");
        // if (penaltyFee.compareTo(BigDecimal.ZERO) == 1) {
        // saveCapitalIncome(capitalIncome.getOrderId(),capitalIncome.getMoney(),penaltyFee,3,"违约金进账");
        // }
    }

    private void handlePenaltyRefund(String businessId, String orderNumber) {
        List<ZtcTransportCapitalLog> transportCapitalLogList = ztcTransportCapitalLogDao
                .getTransportCapitalLogAndTransportById(businessId, true);
        if (transportCapitalLogList == null || transportCapitalLogList.size() == 0) {
            return;
        }
        ZtcWallet wallet;
        for (ZtcTransportCapitalLog transportCapitalLog : transportCapitalLogList) {
            String transportId = transportCapitalLog.getZtcTransport().getId();
            Integer type = transportCapitalLog.getZtcTransport().getType();
            wallet = ztcWalletManager.getWalletByUserId(transportId);
            switch (type) {
                // 省管理公司
                case 1:
                    wallet.setMoney(wallet.getMoney().subtract(transportCapitalLog.getMoney()));
                    ztcWalletDao.update(wallet);
                    saveTransportCapitalLog(transportCapitalLog.getBusinessId(), transportId,
                            transportCapitalLog.getMoney().negate(), wallet.getMoney(), "18", "省级公司退违约金出账");
                    break;
                // 2地级市公司
                case 2:
                    wallet.setMoney(wallet.getMoney().subtract(transportCapitalLog.getMoney()));
                    ztcWalletDao.update(wallet);
                    saveTransportCapitalLog(transportCapitalLog.getBusinessId(), transportId,
                            transportCapitalLog.getMoney().negate(), wallet.getMoney(), "17", "地级公司退违约金出账");
                    break;
                // 运营公司
                case 3:
                    wallet.setMoney(wallet.getMoney().subtract(transportCapitalLog.getMoney()));
                    ztcWalletDao.update(wallet);
                    saveTransportCapitalLog(transportCapitalLog.getBusinessId(), transportId,
                            transportCapitalLog.getMoney().negate(), wallet.getMoney(), "16", "运营公司退违约金出账");
                    break;
                // 车方公司
                case 4:
                    wallet.setMoney(wallet.getMoney().subtract(transportCapitalLog.getMoney()));
                    ztcWalletDao.update(wallet);
                    saveTransportCapitalLog(transportCapitalLog.getBusinessId(), transportId,
                            transportCapitalLog.getMoney().negate(), wallet.getMoney(), "15", "车方公司退违约金出账");
                    break;
                default:
                    break;
            }
        }
        List<ZtcCapitalIncome> capitalIncomeList = ztcCapitalIncomeDao.findBy("orderId", orderNumber);
        if (capitalIncomeList == null || capitalIncomeList.size() == 0) {
            return;
        }
        ZtcCapitalIncome capitalIncome = capitalIncomeList.get(0);
        saveCapitalIncome(capitalIncome.getOrderId(), capitalIncome.getMoney(), capitalIncome.getIncomeMoney().negate(),
                4, "违约金出账");
    }

    /**
     * 处理违约金
     *
     * @param orderMap   订单信息
     * @param penaltyFee 违约金
     */
    private void handlePenaltyFee(Map orderMap, BigDecimal penaltyFee) {
        if (Integer.parseInt(orderMap.get("type").toString()) == 3) {
            // 计算运营公司结算金额并保留两位小数
            BigDecimal operationTransportFee = penaltyFee
                    .multiply(new BigDecimal(orderMap.get("income_scale").toString()).divide(percentage, 2,
                            BigDecimal.ROUND_DOWN));
            if (operationTransportFee.compareTo(BigDecimal.ZERO) > 0) {
                // 保存运营公司余额
                ZtcWallet wallet = ztcWalletManager.getWalletByUserId(orderMap.get("fk_transport_id").toString());
                wallet.setMoney(wallet.getMoney().add(operationTransportFee));
                ztcWalletDao.update(wallet);
                // 保存运营公司资金记录
                saveTransportCapitalLog(orderMap.get("id").toString(), orderMap.get("fk_transport_id").toString(),
                        operationTransportFee, wallet.getMoney(), "12", "运营公司退票违约金进账");
                // 计算除去运营公司结算金额和三级返利金额后还剩的金额
                BigDecimal surplusFee = penaltyFee.subtract(operationTransportFee);
                if (surplusFee.compareTo(BigDecimal.ZERO) > 0) {
                    // 获取当前公司的上级公司
                    ZtcTransport transport = ztcTransportDao.get(orderMap.get("parent_id").toString());
                    // 处理上级公司交易记录及平台资金记录
                    handleTransportCapitalLogAndCapitalIncomeByPenaltyFee(orderMap, surplusFee, transport);
                }
            }

        }
        if (Integer.parseInt(orderMap.get("type").toString()) == 4) {
            // 获取运营公司提成收益比例
            ZtcTransportPercentageScale transportPercentageScale = ztcTransportPercentageScaleDao
                    .getTransportPercentageScaleByTransportId(orderMap.get("parent_id").toString());
            // 计算运营公司的收益及车方公司的收益并保留两位小数
            BigDecimal operationTransportAndCarTransportFee = penaltyFee
                    .multiply(transportPercentageScale.getIncomeScale().divide(percentage, 2, BigDecimal.ROUND_DOWN));
            // 获取车方公司提成收益比例
            transportPercentageScale = ztcTransportPercentageScaleDao
                    .getTransportPercentageScaleByTransportId(orderMap.get("fk_transport_id").toString());
            // 计算车方公司的收益并保留两位小数
            BigDecimal carTransportFee = operationTransportAndCarTransportFee
                    .multiply(transportPercentageScale.getIncomeScale().divide(percentage, 2, BigDecimal.ROUND_DOWN));
            if (carTransportFee.compareTo(BigDecimal.ZERO) > 0) {
                // 获取车方公司资金信息
                ZtcWallet wallet = ztcWalletManager.getWalletByUserId(orderMap.get("fk_transport_id").toString());
                wallet.setMoney(wallet.getMoney().add(carTransportFee));
                // 修改车方公司余额
                ztcWalletDao.update(wallet);
                // 保存车方公司资金记录
                saveTransportCapitalLog(orderMap.get("id").toString(), orderMap.get("fk_transport_id").toString(),
                        carTransportFee, wallet.getMoney(), "11", "车方公司退票违约金进账");
                // 计算运营公司的收益并保留两位小数
                BigDecimal operationTransportFee = operationTransportAndCarTransportFee.subtract(carTransportFee);
                if (operationTransportFee.compareTo(BigDecimal.ZERO) > 0) {
                    // 获取运营公司资金信息
                    wallet = ztcWalletManager.getWalletByUserId(orderMap.get("parent_id").toString());
                    wallet.setMoney(wallet.getMoney().add(operationTransportFee));
                    // 修改运营公司余额
                    ztcWalletDao.update(wallet);
                    // 保存运营公司资金记录
                    saveTransportCapitalLog(orderMap.get("id").toString(), orderMap.get("parent_id").toString(),
                            operationTransportFee, wallet.getMoney(), "12", "运营公司退票违约金进账");
                    // 获取运营公司信息
                    ZtcTransport operationTransport = ztcTransportDao.get(orderMap.get("parent_id").toString());
                    // 计算除去运营公司结算金额和三级返利金额后还剩的金额
                    BigDecimal surplusFee = penaltyFee.subtract(operationTransportFee).subtract(carTransportFee);
                    if (surplusFee.compareTo(BigDecimal.ZERO) > 0) {
                        // 获取运营公司上级公司信息
                        ZtcTransport transport = ztcTransportDao.get(operationTransport.getParentId());
                        // 处理上级公司交易记录及平台资金记录
                        handleTransportCapitalLogAndCapitalIncomeByPenaltyFee(orderMap, surplusFee, transport);
                    }
                }
            }
        }
    }

    private void handleTransportCapitalLogAndCapitalIncomeByPenaltyFee(Map orderMap, BigDecimal surplusFee,
                                                                       ZtcTransport transport) {
        ZtcWallet wallet;
        // 判断上级公司类型
        switch (transport.getType()) {
            // 总公司（平台）
            case 0:
                // 保存平台资金记录
                saveCapitalIncome(orderMap.get("order_number").toString(),
                        new BigDecimal(orderMap.get("order_balance").toString()), surplusFee, 3, "违约金收益");
                break;
            case 1:
                // 获取省级公司提成收益比例
                ZtcTransportPercentageScale transportPercentageScale = ztcTransportPercentageScaleDao
                        .getTransportPercentageScaleByTransportId(transport.getId());
                // 计算省级公司的收益并保留两位小数
                BigDecimal provincialTransportFee = surplusFee
                        .multiply(transportPercentageScale.getIncomeScale().divide(percentage, 2, BigDecimal.ROUND_DOWN));
                if (provincialTransportFee.compareTo(BigDecimal.ZERO) > 0) {
                    // 获取省级公司资金信息
                    wallet = ztcWalletManager.getWalletByUserId(transport.getId());
                    wallet.setMoney(wallet.getMoney().add(provincialTransportFee));
                    // 修改省级公司余额
                    ztcWalletDao.update(wallet);
                    // walletMapper.updateByPrimaryKeySelective(wallet);
                    // 保存省级公司资金记录
                    saveTransportCapitalLog(orderMap.get("id").toString(), transport.getId(), provincialTransportFee,
                            wallet.getMoney(), "14", "省级公司退票违约金进账");
                    if (surplusFee.subtract(provincialTransportFee).compareTo(BigDecimal.ZERO) > 0) {
                        // 保存平台收益记录
                        saveCapitalIncome(orderMap.get("order_number").toString(),
                                new BigDecimal(orderMap.get("order_balance").toString()),
                                surplusFee.subtract(provincialTransportFee), 3, "违约金收益");
                    }
                }
                break;
            case 2:
                // 获取地级公司提成收益比例
                transportPercentageScale = ztcTransportPercentageScaleDao
                        .getTransportPercentageScaleByTransportId(transport.getId());
                // 计算地级公司的收益并保留两位小数
                BigDecimal municipalTransportFee = surplusFee
                        .multiply(transportPercentageScale.getIncomeScale().divide(percentage, 2, BigDecimal.ROUND_DOWN));
                if (municipalTransportFee.compareTo(BigDecimal.ZERO) > 0) {
                    // 获取地级公司资金信息
                    wallet = ztcWalletManager.getWalletByUserId(transport.getId());
                    wallet.setMoney(wallet.getMoney().add(municipalTransportFee));
                    // 修改地级公司余额
                    ztcWalletDao.update(wallet);
                    // walletMapper.updateByPrimaryKeySelective(wallet);
                    // 保存地级公司资金记录
                    saveTransportCapitalLog(orderMap.get("id").toString(), transport.getId(), municipalTransportFee,
                            wallet.getMoney(), "13", "地级公司退票违约金进账");
                    // 获取省级公司提成收益比例
                    transportPercentageScale = ztcTransportPercentageScaleDao
                            .getTransportPercentageScaleByTransportId(transport.getParentId());
                    // 计算省级公司的收益并保留两位小数
                    provincialTransportFee = (surplusFee.subtract(municipalTransportFee)).multiply(
                            transportPercentageScale.getIncomeScale().divide(percentage, 2, BigDecimal.ROUND_DOWN));
                    if (provincialTransportFee.compareTo(BigDecimal.ZERO) > 0) {
                        // 获取省级公司资金信息
                        wallet = ztcWalletManager.getWalletByUserId(transport.getParentId());
                        wallet.setMoney(wallet.getMoney().add(provincialTransportFee));
                        // 修改省级公司余额
                        ztcWalletDao.update(wallet);
                        // walletMapper.updateByPrimaryKeySelective(wallet);
                        // 保存省级公司资金记录
                        saveTransportCapitalLog(orderMap.get("id").toString(), transport.getParentId(),
                                provincialTransportFee, wallet.getMoney(), "14", "省级公司退票违约金进账");
                        if (surplusFee.subtract(municipalTransportFee).subtract(provincialTransportFee)
                                .compareTo(BigDecimal.ZERO) > 0) {
                            // 保存平台收益记录
                            saveCapitalIncome(orderMap.get("order_number").toString(),
                                    new BigDecimal(orderMap.get("order_balance").toString()),
                                    surplusFee.subtract(municipalTransportFee).subtract(provincialTransportFee), 3,
                                    "违约金收益");
                        }
                    }
                }
                break;
            default:
                break;
        }
    }

    /**
     * 保存公司资金交易记录
     *
     * @param orderId      订单ID
     * @param transportId  公司ID
     * @param transportFee 交易金额
     * @param afterBalance 交易后金额
     * @param type         类型
     * @param remark       描述
     */
    private void saveTransportCapitalLog(String orderId, String transportId, BigDecimal transportFee,
                                         BigDecimal afterBalance, String type, String remark) {
        ZtcTransportCapitalLog transportCapitalLog = new ZtcTransportCapitalLog();
        transportCapitalLog.setBusinessId(orderId);
        ZtcTransport transport = new ZtcTransport();
        transport.setId(transportId);
        transportCapitalLog.setZtcTransport(transport);
        // transportCapitalLog.setTransportId(transportId);
        transportCapitalLog.setCreateTime(new Date());
        transportCapitalLog.setMoney(transportFee);
        transportCapitalLog.setAfterBalance(afterBalance);
        transportCapitalLog.setType(type);
        transportCapitalLog.setRemark(remark);
        ztcTransportCapitalLogDao.save(transportCapitalLog);
    }

    /**
     * 保存平台资金交易记录
     *
     * @param orderId        订单ID
     * @param orderBalance   订单金额
     * @param transactionFee 交易金额
     * @param type           类型
     * @param remark         描述
     */
        private void saveCapitalIncome(String orderId, BigDecimal orderBalance, BigDecimal transactionFee, int type,
                                   String remark) {
        ZtcCapitalIncome capitalIncome = new ZtcCapitalIncome();
        capitalIncome.setOrderId(orderId);
        capitalIncome.setMoney(orderBalance);
        capitalIncome.setIncomeMoney(transactionFee);
        capitalIncome.setCreateTime(new Date());
        capitalIncome.setType(type);
        capitalIncome.setRemark(remark);
        ztcCapitalIncomeDao.save(capitalIncome);
    }

    /**
     * 根据公司ID获取最新N条订单信息.
     *
     * @param tid    公司ID
     * @param number 条数(6)
     * @return
     */
    public List<Map> getUpZtcOrderListByTid(String tid, Integer number) {
        return ztcOrderDao.getUpZtcOrderListByTid(tid, number);
    }

    /**
     * 获取快递订单列表.
     */
    public Pager<Map> getExpressZtcOrderList(Integer pageSize, Integer pageNumber,String orderNumber,String startDate,String endDate) {
        return ztcOrderDao.getExpressZtcOrderList(pageSize,pageNumber,orderNumber,startDate,endDate);
    }

    public HashMap<String, Object> getExpressZtcOrderDetail(String oid){
         Map map= ztcOrderDao.getExpressZtcOrderDetail(oid);
         if(map==null){
             return JsonWrapper.failureWrapperMsg("订单不存在");
         }
        return JsonWrapper.successWrapper(map);
    }
}
